home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / AppleShare API / Extras / ServerControlSnippets.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-03  |  25.7 KB  |  1,073 lines  |  [TEXT/MPS ]

  1. /*
  2. **    Server Control Snippets
  3. **    The server control code snippets found in the AppleShare 3.0 Developer's
  4. **    Kit Server Control and Server Event Handling document.
  5. **
  6. **    by J. Luther, Apple Developer Technical Support
  7. **    Copyright Apple Computer, Inc. 1992-1994
  8. **    All rights reserved
  9. **
  10. **    Port from Pascal to C - 9/8/1994 JML
  11. **
  12. **    Here's the deal with the code in this file.
  13. **
  14. **    For each server control call, there is a function named MySCxxxx. The
  15. **    typical MySCxxxx function shows how to fill in the parameter block, make
  16. **    the server control call, and return any result values the server control
  17. **    returns. In addition, I've made every attempt to make the server control
  18. **    calls supported by Macintosh File Sharing act like the same server
  19. **    control calls under AppleShare. In some cases, that means I've filled
  20. **    in the return values not supplied by old versions of Macintosh File
  21. **    Sharing. In other cases (i.e., SCGetExpFldr), I've had to add code just
  22. **    to make the server control call work as advertised.
  23. **
  24. **    For some server control calls, I've added another code snippet or
  25. **    function to show a common use of that particular server control call.
  26. **    Here's what you'll find:
  27. **
  28. **    •    There are code snippets that get the server version, status, and
  29. **        setup information and then store that information in global variables
  30. **        for later use by other functions. In some case, other code depends
  31. **        on those global variables being initialized and that is noted
  32. **        where applicable.
  33. **
  34. **    •    There are functions that show how to enumerate the list of exported
  35. **        volumes and folder, enumerate the list of installed server event
  36. **        handlers, enumerate the list of connected users, get a users mount
  37. **        information for all volumes or folders mounted, disconnect a user
  38. **        from the server, send a message to all connected users, and disconnect
  39. **        the users of a specified volume.
  40. **
  41. **    All the test functions and snippets are marked like this:
  42. **        ••• Test Code •••
  43. **    Some code snippets are commented out under the Test Code markers, because
  44. **    they won't compile there. They can be found again in the main function.
  45. */
  46.  
  47. /*****************************************************************************/
  48.  
  49. #include <Traps.h>
  50. #include <AppleTalk.h>
  51. #include <Errors.h>
  52. #include <Memory.h>
  53. #include "ServerEventIntf.h"
  54. #include "ServerControlIntf.h"
  55.  
  56. /*****************************************************************************/
  57.  
  58. /*
  59. **    File Sharing 4.0 supports most server control calls just like AppleShare.
  60. **    The only exceptions are SCShutDown and SCDisconnect which ignore the
  61. **    flags and messagePtr parameters because those calls were supported by
  62. **    the old File Sharing code and some callers didn't bother to set
  63. **    messagePtr to NULL.
  64. */
  65.  
  66. enum
  67. {
  68.     kNewFileSharingVersion = 0x3e    /* File Sharing 4.0's version number */
  69. };
  70.  
  71. /*****************************************************************************/
  72.  
  73. /*
  74. **    Globals
  75. */
  76.  
  77. OSErr            gErr;
  78. Boolean            gHasServerDispatch;
  79.  
  80. /* results from SCServerVersion */
  81. Str31            gServerExtensionName;
  82. short            gServerType;
  83. short            gServerVersion;
  84.  
  85. /* results from SCPollServer */
  86. short            gServerState;
  87. short            gDisconnectState;
  88. short            gServerError;
  89. long            gSecondsLeft;
  90.  
  91. /* results from SCGetSetupInfo */
  92. SetupInfoRec    gSetupInfoRec;
  93. short            gMaxVolumes;
  94. short            gMaxExpFolders;
  95. short            gCurMaxSessions;
  96.  
  97. /*****************************************************************************/
  98.  
  99. /*
  100. **    Prototypes
  101. */
  102.  
  103. OSErr    MySCServerVersion(StringPtr extNamePtr,
  104.                           short *serverType,
  105.                           short *serverVersion);
  106.  
  107. OSErr    MySCPollServer(short *serverState,
  108.                        short *disconnectState,
  109.                        short *serverError,
  110.                        long *secondsLeft);
  111.  
  112. OSErr    MySCGetSetupInfo(SetupInfoRec *setupPtr,
  113.                          short *maxVolumes,
  114.                          short *maxExpFolders,
  115.                          short *curMaxSessions);
  116.  
  117. OSErr    MySCGetExpFldr(short index,
  118.                        StringPtr namePtr,
  119.                        short *vRefNum,
  120.                        short *logins,
  121.                        long *dirID);
  122.  
  123. OSErr    MySCGetServerStatus(StringPtr namePtr,
  124.                             short *serverFlags,
  125.                             short *numSessions,
  126.                             long *userListModDate,
  127.                             short *activity,
  128.                             long *volListModDate);
  129.  
  130. OSErr    MySCGetServerEventProc(QHdrPtr *theSEQHdrPtr);
  131.  
  132. OSErr    MySCGetUserNameRec(StringPtr namePtr,
  133.                            long *position,
  134.                            long *unRecID,
  135.                            long *userID,
  136.                            long *loginTime,
  137.                            long *lastUseTime,
  138.                            AddrBlock *socketNum);
  139.  
  140. OSErr    MySCGetUserMountInfo(short vRefNum,
  141.                              long unRecID,
  142.                              short *filesOpen,
  143.                              short *writeableFiles,
  144.                              Boolean *mounted,
  145.                              Boolean *mountedAsOwner);
  146.  
  147. OSErr    MySCStartServer(void);
  148.  
  149. OSErr    MySCShutDown(short numMinutes,
  150.                      short flags,
  151.                      StringPtr messagePtr);
  152.  
  153. OSErr    MySCCancelShutDown(void);
  154.  
  155. OSErr    MySCWakeServer(void);
  156.  
  157. OSErr    MySCSleepServer(short numMinutes,
  158.                         short flags,
  159.                         StringPtr messagePtr);
  160.  
  161. OSErr    MySCSetSetupInfo(SetupInfoRecPtr setupPtr);
  162.  
  163. OSErr    MySCDisconnect(long *discArrayPtr,
  164.                        short arrayCount,
  165.                        short numMinutes,
  166.                        short flags,
  167.                        StringPtr messagePtr);
  168.  
  169. OSErr    MySCSendMessage(long *discArrayPtr,
  170.                         short arrayCount,
  171.                         short flags,
  172.                         StringPtr messagePtr);
  173.  
  174. OSErr    MySCSetCopyProtect(StringPtr namePtr,
  175.                            short vRefNum,
  176.                            long dirID);
  177.  
  178. OSErr    MySCClrCopyProtect(StringPtr namePtr,
  179.                            short vRefNum,
  180.                            long dirID);
  181.  
  182. OSErr    MySCDisconnectVolUsers(long *discArrayPtr,
  183.                                short arrayCount,
  184.                                short numMinutes,
  185.                                short flags,
  186.                                StringPtr messagePtr);
  187.  
  188. /*****************************************************************************/
  189. /*****************************************************************************/
  190.  
  191. /*
  192. **    The following three functions (NumToolboxTraps, GetTrapType, and
  193. **    TrapAvailable) are from Inside Macintosh Volume VI.
  194. */
  195.  
  196. static    short    NumToolboxTraps(void)
  197. {
  198.     if    (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  199.         return ( 0x0200 );
  200.     else
  201.         return ( 0x0400 );
  202. }
  203.  
  204.  
  205. static    TrapType    GetTrapType(short theTrap)
  206. {
  207.     if ( (theTrap & 0x0800) > 0)
  208.         return ( ToolTrap );
  209.     else
  210.         return ( OSTrap );
  211. }
  212.  
  213. static    Boolean    TrapAvailable(short    theTrap)
  214. {
  215.     TrapType    tType;
  216.     
  217.     tType = GetTrapType(theTrap);
  218.     if (tType == ToolTrap)
  219.     {
  220.         theTrap = theTrap & 0x07FF;
  221.         if ( theTrap >= NumToolboxTraps() )
  222.             theTrap = _Unimplemented;
  223.     }
  224.     return ( NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented, ToolTrap) );
  225. }
  226.  
  227. /*****************************************************************************/
  228. /*****************************************************************************/
  229.  
  230. /*
  231. **    This function calls SCServerVersion to get the file
  232. **    server extension's name and the server's type and
  233. **    version.
  234. **
  235. **    Note:    The server version (scServerVersion) returned by
  236. **            Macintosh File Sharing servers is not valid when
  237. **            the file server is not running.
  238. */
  239.  
  240. OSErr    MySCServerVersion(StringPtr extNamePtr,
  241.                           short *serverType,
  242.                           short *serverVersion)
  243. {
  244.     SCParamBlockRec    scPB;
  245.     OSErr            result;
  246.     
  247.     scPB.versionPB.scCode = SCServerVersion;
  248.     scPB.versionPB.scExtNamePtr = extNamePtr;
  249.     
  250.     result = SyncServerDispatch(&scPB);
  251.     if ( result == noErr )
  252.     {
  253.         *serverType = scPB.versionPB.scServerType;
  254.         *serverVersion = scPB.versionPB.scServerVersion;
  255.     }
  256.     
  257.     return ( result );
  258. }
  259.  
  260. /*
  261. **    ••• Test Code •••
  262. **
  263. **    Get the server version information and store it in
  264. **    global variables for user later
  265. **
  266. **    gErr = MySCServerVersion(gServerExtensionName, &gServerType, &gServerVersion);
  267. */
  268.  
  269. /*****************************************************************************/
  270.  
  271. /*
  272. **    This function calls SCPollServer to find out what the
  273. **    server is doing.
  274. */
  275.  
  276. OSErr    MySCPollServer(short *serverState,
  277.                        short *disconnectState,
  278.                        short *serverError,
  279.                        long *secondsLeft)
  280. {
  281.     SCParamBlockRec    scPB;
  282.     OSErr            result;
  283.     
  284.     scPB.pollServerPB.scCode = SCPollServer;
  285.       /* Macintosh File Sharing doesn't return scSecondsLeft so zero it. */
  286.     scPB.pollServerPB.scSecondsLeft = 0;
  287.     
  288.     result = SyncServerDispatch(&scPB);
  289.     if ( result == noErr )
  290.     {
  291.         *serverState = scPB.pollServerPB.scServerState;
  292.         *disconnectState = scPB.pollServerPB.scDisconnectState;
  293.         *serverError = scPB.pollServerPB.scServerError;
  294.         *secondsLeft = scPB.pollServerPB.scSecondsLeft;
  295.     }
  296.     
  297.     return ( result );
  298. }
  299.  
  300. /*
  301. **    ••• Test Code •••
  302. **    Find out what the server's doing and store it in
  303. **    global variables for user later
  304. **
  305. **    gErr = MySCPollServer(gServerState, gDisconnectState, gServerError, gSecondsLeft);
  306. **
  307. */
  308.  
  309. /*****************************************************************************/
  310.  
  311. /*
  312. **    This function calls SCGetSetupInfo to get the file
  313. **    server's setup information. If the server type is an old
  314. **    Macintosh File Sharing server, then this function fills
  315. **    in the fields that aren't returned by the server control
  316. **    call. This function depends on gServerType and
  317. **    gServerVersion being initialized with SCServerVersion.
  318. */
  319.  
  320. OSErr    MySCGetSetupInfo(SetupInfoRec *setupPtr,
  321.                          short *maxVolumes,
  322.                          short *maxExpFolders,
  323.                          short *curMaxSessions)
  324. {
  325.     SCParamBlockRec    scPB;
  326.     OSErr            result;
  327.     
  328.     scPB.setupPB.scCode = SCGetSetupInfo;
  329.     scPB.setupPB.scSetupPtr = setupPtr;
  330.     
  331.     result = SyncServerDispatch(&scPB);
  332.     if ( result == noErr )
  333.     {
  334.         if ( (gServerType == MFSType) && (gServerVersion < kNewFileSharingVersion) )
  335.         {
  336.             *maxVolumes = 10;
  337.             *maxExpFolders = 10;
  338.             *curMaxSessions = setupPtr->SIMaxLogins;
  339.         }
  340.         else
  341.         {
  342.             *maxVolumes = scPB.setupPB.scMaxVolumes;
  343.             *maxExpFolders = scPB.setupPB.scMaxExpFolders;
  344.             *curMaxSessions = scPB.setupPB.scCurMaxSessions;
  345.         }
  346.     }
  347.     
  348.     return ( result );
  349. }
  350.  
  351. /*
  352. **    ••• Test Code •••
  353. **    Get the server's setup information and store it in
  354. **    global variables for user later
  355. **
  356. **    gErr = MySCGetSetupInfo(&gSetupInfoRec, &gMaxVolumes, &gMaxExpFolders, &gCurMaxSessions);
  357. */
  358.  
  359. /*****************************************************************************/
  360.  
  361. /*
  362. **    This function calls SCGetExpFldr to get the export
  363. **    information for shared volumes and folders at the index
  364. **    position specified. This function depends on gServerType
  365. **    being initialized with SCServerVersion.
  366. */
  367.  
  368. OSErr    MySCGetExpFldr(short index,
  369.                        StringPtr namePtr,
  370.                        short *vRefNum,
  371.                        short *logins,
  372.                        long *dirID)
  373. {
  374.     SCParamBlockRec    scPB;
  375.     OSErr            result;
  376.     
  377.     scPB.standardPB.scCode = SCGetExpFldr;
  378.     
  379.     /* Initialize scVRefNum to 0 so we can tell if */
  380.     /* SCGetExpFldr returned something when used with */
  381.     /* Macintosh File Sharing */
  382.     scPB.standardPB.scVRefNum = 0;
  383.     
  384.     if (index < 0)
  385.     {
  386.         /* Old versions of File Sharing trashes memory if */
  387.         /* (scIndex < 0) and (scNamePtr != NULL), so we'll */
  388.         /* prevent that from happening here. */
  389.         scPB.standardPB.scNamePtr = NULL;
  390.         
  391.         /* and we'll return an empty string */
  392.         if ( namePtr != NULL )
  393.         {
  394.             namePtr[0] = 0;
  395.         }
  396.     }
  397.     else
  398.     {
  399.         scPB.standardPB.scNamePtr = namePtr;
  400.     }
  401.     scPB.standardPB.scIndex = index;
  402.     
  403.     result = SyncServerDispatch(&scPB);
  404.     if ( result == noErr )
  405.     {
  406.         if ( (gServerType == MFSType) && (gServerVersion < kNewFileSharingVersion) )
  407.         {
  408.             if ( scPB.standardPB.scVRefNum != 0 )
  409.             {
  410.                 *vRefNum = scPB.standardPB.scVRefNum;
  411.                 *logins = 0;
  412.                 *dirID = scPB.standardPB.scDirID;
  413.             }
  414.             else
  415.             {
  416.                 /* there's nothing at this index position */
  417.                   /* so force the error code to make it act */
  418.                   /* like AppleShare */
  419.                 result = fnfErr;
  420.             }
  421.         }
  422.         else
  423.         {
  424.             *vRefNum = scPB.standardPB.scVRefNum;
  425.             *logins = scPB.standardPB.scLogins;
  426.             *dirID = scPB.standardPB.scDirID;
  427.         }
  428.     }
  429.     
  430.     return ( result );
  431. }
  432.  
  433. /*
  434. **    ••• Test Code •••
  435. **
  436. **    Enumerate the list of exported volumes and folders
  437. */
  438.  
  439. void    GetAllExpFldrs(void)
  440. {
  441.     short    index;
  442.     Str15    shortName;    /* only 13 characters are needed... */
  443.     short    vRefNum;
  444.     short    logins;
  445.     long    dirID;
  446.     OSErr    result;
  447.     
  448.     for ( index = -gMaxVolumes; index <= gMaxExpFolders; ++index )
  449.     {
  450.         if ( index != 0 )    /* index 0 is undefined */
  451.         {
  452.             result = MySCGetExpFldr(index, shortName, &vRefNum, &logins, &dirID);
  453.             if ( result == noErr )
  454.             {
  455.                 if ( index < 0 )
  456.                 {
  457.                     /* Do something with the exported volume */
  458.                     /* information */
  459.                 }
  460.                 else
  461.                 {
  462.                     /* Do something with the exported folder */
  463.                     /* information */
  464.                 }
  465.             }
  466.             else if ( result != fnfErr )
  467.             {
  468.                 /* fnfErr only means there is nothing at this index position. */
  469.                 /* If not fnfErr, then handle any unexpected errors */
  470.             }
  471.         }
  472.     }
  473. }
  474.  
  475. /*****************************************************************************/
  476.  
  477. /*
  478. **    This function calls SCGetServerStatus to get the file
  479. **    server's current status information.
  480. */
  481.  
  482. OSErr    MySCGetServerStatus(StringPtr namePtr,
  483.                             short *serverFlags,
  484.                             short *numSessions,
  485.                             long *userListModDate,
  486.                             short *activity,
  487.                             long *volListModDate)
  488. {
  489.     SCParamBlockRec    scPB;
  490.     OSErr            result;
  491.     
  492.     scPB.statusPB.scCode = SCGetServerStatus;
  493.     scPB.statusPB.scNamePtr = namePtr;
  494.     
  495.     result = SyncServerDispatch(&scPB);
  496.     if ( result == noErr )
  497.     {
  498.         *serverFlags = scPB.statusPB.scServerFlags;
  499.         *numSessions = scPB.statusPB.scNumSessions;
  500.         *userListModDate = scPB.statusPB.scUserListModDate;
  501.         *activity = scPB.statusPB.scActivity;
  502.         *volListModDate = scPB.statusPB.scVolListModDate;
  503.     }
  504.     
  505.     return ( result );
  506. }
  507.  
  508. /*****************************************************************************/
  509.  
  510. /*
  511. **    This function calls SCGetServerEventProc to get a
  512. **    pointer to the head of the server event handler queue.
  513. */
  514.  
  515. OSErr    MySCGetServerEventProc(QHdrPtr *theSEQHdrPtr)
  516. {
  517.     SCParamBlockRec    scPB;
  518.     OSErr            result;
  519.     
  520.     scPB.serverEventPB.scCode = SCGetServerEventProc;
  521.     
  522.     result = SyncServerDispatch(&scPB);
  523.     if ( result == noErr )
  524.     {
  525.         *theSEQHdrPtr = (QHdrPtr)scPB.serverEventPB.scSEQEntryPtr;
  526.     }
  527.     
  528.     return ( result );
  529. }
  530.  
  531. /*
  532. **    ••• Test Code •••
  533. **
  534. **    Enumerate the list of installed server event handlers.
  535. */
  536.  
  537. void    GetServerEventHandlers(void)
  538. {
  539.     OSErr            result;
  540.     QHdrPtr            theSEQHdrPtr;
  541.     tSEQEntryPtr    theSEQEntryPtr;
  542.     
  543.     result = MySCGetServerEventProc(&theSEQHdrPtr);
  544.     if ( result == noErr )
  545.     {
  546.         theSEQEntryPtr = (tSEQEntryPtr)theSEQHdrPtr->qHead;
  547.         while ( theSEQEntryPtr != NULL )
  548.         {
  549.             /* Do something with the tSEQentry pointed to */
  550.             /* by theSEQEntryPtr */
  551.  
  552.             /* Then, move pointer to next entry (if any) */
  553.             theSEQEntryPtr = (tSEQEntryPtr)theSEQEntryPtr->SEQentry.qLink;
  554.         }
  555.     }
  556.     else
  557.     {
  558.         /* handle any errors */
  559.     }
  560. }
  561.  
  562. /*****************************************************************************/
  563.  
  564. /*
  565. **    This function calls SCGetUserNameRec to retrieve
  566. **    statistics on a connected user.
  567. */
  568.  
  569. OSErr    MySCGetUserNameRec(StringPtr namePtr,
  570.                            long *position,
  571.                            long *unRecID,
  572.                            long *userID,
  573.                            long *loginTime,
  574.                            long *lastUseTime,
  575.                            AddrBlock *socketNum)
  576. {
  577.     SCParamBlockRec    scPB;
  578.     OSErr            result;
  579.     
  580.     scPB.userInfoPB.scCode = SCGetUserNameRec;
  581.     scPB.userInfoPB.scNamePtr = namePtr;
  582.     scPB.userInfoPB.scPosition = *position;
  583.     
  584.     result = SyncServerDispatch(&scPB);
  585.     if ( result == noErr )
  586.     {
  587.         *position = scPB.userInfoPB.scPosition;
  588.         *unRecID = scPB.userInfoPB.scUNRecID;
  589.         *userID = scPB.userInfoPB.scUserID;
  590.         *loginTime = scPB.userInfoPB.scLoginTime;
  591.         *lastUseTime = scPB.userInfoPB.scLastUseTime;
  592.         *socketNum = scPB.userInfoPB.scSocketNum;
  593.     }
  594.     
  595.     return ( result );
  596. }
  597.  
  598. /*
  599. **    ••• Test Code •••
  600. **
  601. **    Enumerate the list of users logged on
  602. */
  603.  
  604. void    GetAllUserNameRecs(void)
  605. {
  606.     OSErr        result;
  607.     Str31        userName;
  608.     long        position;
  609.     long        unRecID;
  610.     long        userID;
  611.     long        loginTime;
  612.     long        lastUseTime;
  613.     AddrBlock    socketNum;
  614.     
  615.     position = 0;
  616.     do
  617.     {
  618.         result = MySCGetUserNameRec(userName, &position, &unRecID, &userID,
  619.                                     &loginTime, &lastUseTime, &socketNum);
  620.         if ( result == noErr )
  621.         {
  622.             /* Do something with the user information returned */
  623.         }
  624.         else if ( result != fnfErr ) 
  625.         {
  626.             /* fnfErr only means there are no more users */
  627.             /* If not fnfErr, then handle any unexpected errors */
  628.         }
  629.     } while ( result == noErr );
  630. }
  631.  
  632. /*****************************************************************************/
  633.  
  634. /*
  635. **    This function calls SCGetUserMountInfo to return
  636. **    information telling how a user is using a particular
  637. **    volume or exported folder.
  638. */
  639.  
  640. OSErr    MySCGetUserMountInfo(short vRefNum,
  641.                              long unRecID,
  642.                              short *filesOpen,
  643.                              short *writeableFiles,
  644.                              Boolean *mounted,
  645.                              Boolean *mountedAsOwner)
  646. {
  647.     SCParamBlockRec    scPB;
  648.     OSErr            result;
  649.     
  650.     scPB.volMountedPB.scCode = SCGetUserMountInfo;
  651.     scPB.volMountedPB.scVRefNum = vRefNum;
  652.     scPB.volMountedPB.scUNRecID = unRecID;
  653.  
  654.     result = SyncServerDispatch(&scPB);
  655.  
  656.     *filesOpen = scPB.volMountedPB.scFilesOpen;
  657.     *writeableFiles = scPB.volMountedPB.scWriteableFiles;
  658.     *mounted = scPB.volMountedPB.scMounted;
  659.     *mountedAsOwner = scPB.volMountedPB.scMountedAsOwner;
  660.     
  661.     return ( result );
  662. }
  663.  
  664. /*
  665. **    ••• Test Code •••
  666. **
  667. **    Get the user mount information for all volumes and
  668. **    exported folders a user has mounted.
  669. */
  670.  
  671. void    GetAllUserMountInfo(long unRecID)
  672. {
  673.     OSErr    result;
  674.     short    index;
  675.     short    filesOpen;
  676.     short    writeableFiles;
  677.     Boolean    mounted;
  678.     Boolean    mountedAsOwner;
  679.     
  680.     for ( index = -gMaxVolumes; index <= gMaxExpFolders; ++index )
  681.     {
  682.         if ( index != 0 ) /* index 0 is undefined */
  683.         {
  684.             result = MySCGetUserMountInfo(index, unRecID, &filesOpen, &writeableFiles,
  685.                                           &mounted, &mountedAsOwner);
  686.             if ( (result == noErr) && (mounted == true) )
  687.             {
  688.                 /* Do something with the information returned */
  689.             }
  690.         }
  691.     }
  692. }
  693.  
  694. /*****************************************************************************/
  695.  
  696. /*
  697. **    This function calls SCStartServer to start the Macintosh
  698. **    File Sharing server.
  699. */
  700.  
  701. OSErr    MySCStartServer(void)
  702. {
  703.     SCParamBlockRec    scPB;
  704.     
  705.     scPB.startPB.scCode = SCStartServer;
  706.     scPB.startPB.scStartSelect = kCurInstalled;
  707.     scPB.startPB.scEventSelect = kFinderExtn;
  708.     
  709.     return ( SyncServerDispatch(&scPB) );
  710. }
  711.  
  712. /*****************************************************************************/
  713.  
  714. /*
  715. **    This function calls SCShutDown to shut down the file
  716. **    server.
  717. **
  718. **    Note:    File Sharing ignores the messagePtr parameter. Even the new
  719. **            versions, because the Finder doesn't fill in the messagePtr
  720. **            and flags field in the parameter block (it never had to in
  721. **            the past).
  722. */
  723.  
  724. OSErr    MySCShutDown(short numMinutes,
  725.                      short flags,
  726.                      StringPtr messagePtr)
  727. {
  728.     SCParamBlockRec    scPB;
  729.     
  730.     scPB.disconnectPB.scCode = SCShutDown;
  731.     scPB.disconnectPB.scNumMinutes = numMinutes;
  732.     scPB.disconnectPB.scFlags = flags;
  733.     scPB.disconnectPB.scMessagePtr = messagePtr;
  734.     
  735.     return ( SyncServerDispatch(&scPB) );
  736. }
  737.  
  738. /*****************************************************************************/
  739.  
  740. /*
  741. **    This function calls SCCancelShutDown to cancel the
  742. **    shutdown or disconnect in progress.
  743. */
  744.  
  745. OSErr    MySCCancelShutDown(void)
  746. {
  747.     SCParamBlockRec    scPB;
  748.     
  749.     scPB.disconnectPB.scCode = SCCancelShutDown;
  750.  
  751.     return ( SyncServerDispatch(&scPB) );
  752. }
  753.  
  754. /*****************************************************************************/
  755.  
  756. /*
  757. **    This function calls SCWakeServer to wake up a sleeping
  758. **    AppleShare 3.0 file server.
  759. */
  760.  
  761. OSErr    MySCWakeServer(void)
  762. {
  763.     SCParamBlockRec    scPB;
  764.     
  765.     scPB.startPB.scCode = SCWakeServer;
  766.  
  767.     return ( SyncServerDispatch(&scPB) );
  768. }
  769.  
  770. /*****************************************************************************/
  771.  
  772. /*
  773. **    This function calls SCSleepServer to shut down the file
  774. **    server temporarily.
  775. */
  776.  
  777. OSErr    MySCSleepServer(short numMinutes,
  778.                         short flags,
  779.                         StringPtr messagePtr)
  780. {
  781.     SCParamBlockRec    scPB;
  782.     
  783.     scPB.disconnectPB.scCode = SCSleepServer;
  784.     scPB.disconnectPB.scNumMinutes = numMinutes;
  785.     scPB.disconnectPB.scFlags = flags;
  786.     scPB.disconnectPB.scMessagePtr = messagePtr;
  787.     
  788.     return ( SyncServerDispatch(&scPB) );
  789. }
  790.  
  791. /*****************************************************************************/
  792.  
  793. /*
  794. **    This function calls SCSetSetupInfo to set the file
  795. **    server's setup information.
  796. */
  797.  
  798. OSErr    MySCSetSetupInfo(SetupInfoRecPtr setupPtr)
  799. {
  800.     SCParamBlockRec    scPB;
  801.     
  802.     scPB.setupPB.scCode = SCSetSetupInfo;
  803.     scPB.setupPB.scSetupPtr = setupPtr;
  804.     
  805.     return ( SyncServerDispatch(&scPB) );
  806. }
  807.  
  808. /*****************************************************************************/
  809.  
  810. /*
  811. **    This function calls SCDisconnect to disconnect some
  812. **    users. Although Macintosh File Sharing implements
  813. **    SCDisconnect, there is no way to use it with old
  814. **    versions of File Sharing because old File Sharing
  815. **    doesn't implement the SCGetUserNameRec call.
  816. **
  817. **    Note:    File Sharing ignores the messagePtr parameter. Even the new
  818. **            versions, because the Finder doesn't fill in the messagePtr
  819. **            and flags field in the parameter block (it never had to in
  820. **            the past).
  821. */
  822.  
  823. OSErr    MySCDisconnect(long *discArrayPtr,
  824.                        short arrayCount,
  825.                        short numMinutes,
  826.                        short flags,
  827.                        StringPtr messagePtr)
  828. {
  829.     SCParamBlockRec    scPB;
  830.     
  831.     scPB.disconnectPB.scDiscArrayPtr = discArrayPtr;
  832.     scPB.disconnectPB.scArrayCount = arrayCount;
  833.     scPB.disconnectPB.scCode = SCDisconnect;
  834.     scPB.disconnectPB.scNumMinutes = numMinutes;
  835.     scPB.disconnectPB.scFlags = flags;
  836.     scPB.disconnectPB.scMessagePtr = messagePtr;
  837.     
  838.     return ( SyncServerDispatch(&scPB) );
  839. }
  840.  
  841. /*
  842. **    ••• Test Code •••
  843. **
  844. **    Disconnect the user specified in 10 minutes with a
  845. **    message.
  846. */
  847.  
  848. void    DisconnectUser(long unRecID)
  849. {
  850.     OSErr        result;
  851.     short        arrayCount;
  852.     short        numMinutes;
  853.     short        flags;
  854.     tLoginMsg    message = "\pGoodbye.";
  855.     
  856.     arrayCount = 1;  /* one user */
  857.     numMinutes = 10;
  858.     flags = UNRFSendMsgMask; /* send a message */
  859.     result = MySCDisconnect(&unRecID, arrayCount, numMinutes, flags, message);
  860.     if ( result == noErr )
  861.     {
  862.         /* The disconnect was started */
  863.     }
  864.     else
  865.     {
  866.         /* Handle any errors */
  867.     }
  868. }
  869.  
  870. /*****************************************************************************/
  871.  
  872. /*
  873. **    This function calls SCSendMessage to send a message to
  874. **    some users.
  875. */
  876.  
  877. OSErr    MySCSendMessage(long *discArrayPtr,
  878.                         short arrayCount,
  879.                         short flags,
  880.                         StringPtr messagePtr)
  881. {
  882.     SCParamBlockRec    scPB;
  883.     
  884.     scPB.disconnectPB.scDiscArrayPtr = discArrayPtr;
  885.     scPB.disconnectPB.scArrayCount = arrayCount;
  886.     scPB.disconnectPB.scCode = SCSendMessage;
  887.     scPB.disconnectPB.scFlags = flags;
  888.     scPB.disconnectPB.scMessagePtr = messagePtr;
  889.     
  890.     return ( SyncServerDispatch(&scPB) );
  891. }
  892.  
  893. /*
  894. **    ••• Test Code •••
  895. **
  896. **    Send a message to all connected users
  897. */
  898.  
  899. void    SendMessageToAll(void)
  900. {
  901.     /* This routine depends on gCurMaxSessions being */
  902.     /* initialized with SCGetSetupInfo. */
  903.     
  904.     OSErr            result;
  905.     long            *arrayPosPtr;
  906.     SCParamBlockRec    scPB;
  907.  
  908.     long            *discArrayPtr;
  909.     short            arrayCount;
  910.     short            flags;
  911.     tLoginMsg        message = "\pMoof!(tm)";
  912.     
  913.     /* Allocate an array large enough to get all users */
  914.     discArrayPtr = (long *)NewPtr(sizeof(long) * gCurMaxSessions);
  915.     if ( discArrayPtr != NULL )
  916.     {
  917.         scPB.userInfoPB.scPosition = 0;
  918.         arrayCount = 0;
  919.         arrayPosPtr = discArrayPtr;
  920.         do
  921.         {
  922.             /* Bbuild list of users with SCGEtUserNameRec */
  923.             scPB.userInfoPB.scCode = SCGetUserNameRec;
  924.             scPB.userInfoPB.scNamePtr = NULL;
  925.             result = SyncServerDispatch(&scPB);
  926.             if ( result == noErr )
  927.             {
  928.                 /* Add user to array */
  929.                 *arrayPosPtr = scPB.userInfoPB.scUNRecID;
  930.                 ++arrayPosPtr;
  931.                 ++arrayCount;
  932.             }
  933.         } while ( result == noErr );
  934.         
  935.         if ( arrayCount > 0 )
  936.         {
  937.             flags = UNRFSendMsgMask; /* Send a message */
  938.             result = MySCSendMessage(discArrayPtr, arrayCount, flags, message);
  939.             if ( result == noErr )
  940.             {
  941.                 /* The message was sent */
  942.             }
  943.             else
  944.             {
  945.                 /* Handle any errors from SCSendMessage */
  946.             }
  947.         }
  948.         else
  949.         {
  950.             /* There are no users connected */
  951.             /* do nothing */
  952.         }
  953.         DisposPtr((Ptr)discArrayPtr);
  954.     }
  955.     else
  956.     {
  957.         /* Handle memory manager error */
  958.     }
  959. }
  960.  
  961. /*****************************************************************************/
  962.  
  963. /*
  964. **    This function calls SCSetCopyProtect to set the copy
  965. **    protect status of a file.
  966. */
  967.  
  968. OSErr    MySCSetCopyProtect(StringPtr namePtr,
  969.                            short vRefNum,
  970.                            long dirID)
  971. {
  972.     SCParamBlockRec    scPB;
  973.     
  974.     scPB.standardPB.scNamePtr = namePtr;
  975.     scPB.standardPB.scVRefNum = vRefNum;
  976.     scPB.standardPB.scCode = SCSetCopyProtect;
  977.     scPB.standardPB.scDirID = dirID;
  978.     
  979.     return ( SyncServerDispatch(&scPB) );
  980. }
  981.  
  982. /*****************************************************************************/
  983.  
  984. /*
  985. **    This function calls SCClrCopyProtect to clear the copy
  986. **    protect status of a file.
  987. */
  988.  
  989. OSErr    MySCClrCopyProtect(StringPtr namePtr,
  990.                            short vRefNum,
  991.                            long dirID)
  992. {
  993.     SCParamBlockRec    scPB;
  994.     
  995.     scPB.standardPB.scNamePtr = namePtr;
  996.     scPB.standardPB.scVRefNum = vRefNum;
  997.     scPB.standardPB.scCode = SCClrCopyProtect;
  998.     scPB.standardPB.scDirID = dirID;
  999.     
  1000.     return ( SyncServerDispatch(&scPB) );
  1001. }
  1002.  
  1003. /*****************************************************************************/
  1004.  
  1005. /*
  1006. **    This function calls SCDisconnectVolUsers to disconnect
  1007. **    the users of specified volumes.
  1008. */
  1009.  
  1010. OSErr    MySCDisconnectVolUsers(long *discArrayPtr,
  1011.                                short arrayCount,
  1012.                                short numMinutes,
  1013.                                short flags,
  1014.                                StringPtr messagePtr)
  1015. {
  1016.     SCParamBlockRec    scPB;
  1017.     
  1018.     scPB.disconnectPB.scDiscArrayPtr = discArrayPtr;
  1019.     scPB.disconnectPB.scArrayCount = arrayCount;
  1020.     scPB.disconnectPB.scCode = SCDisconnectVolUsers;
  1021.     scPB.disconnectPB.scNumMinutes = numMinutes;
  1022.     scPB.disconnectPB.scFlags = flags;
  1023.     scPB.disconnectPB.scMessagePtr = messagePtr;
  1024.     
  1025.     return ( SyncServerDispatch(&scPB) );
  1026. }
  1027.  
  1028. /*
  1029. **    ••• Test Code •••}
  1030. **
  1031. **    Disconnect the users of the specified volume in
  1032. **    10 minutes with a message.
  1033. */
  1034.  
  1035. void    DisconnectVolUsers(short vRefNum)
  1036. {
  1037.     OSErr        result;
  1038.     long        discToDisconnect;
  1039.     short        arrayCount;
  1040.     short        numMinutes;
  1041.     short        flags;
  1042.     tLoginMsg    message = "\pA volume is going away.";
  1043.     
  1044.     discToDisconnect = vRefNum; /* Note: short -> long */
  1045.     arrayCount = 1;
  1046.     numMinutes = 10;
  1047.     flags = UNRFSendMsgMask; /* send a message */
  1048.     result = MySCDisconnectVolUsers(&discToDisconnect, arrayCount, numMinutes,
  1049.                                     flags, message);
  1050.     if ( result == noErr )
  1051.     {
  1052.         /* The disconnect was started */
  1053.     }
  1054.     else
  1055.     {
  1056.         /* Handle any errors */
  1057.     }
  1058. }
  1059.  
  1060. /*****************************************************************************/
  1061.  
  1062. void    main(void)
  1063. {
  1064.     /* You MUST make sure ServerDispatch is available before calling it */
  1065.     gHasServerDispatch = TrapAvailable(ServerDispatch);
  1066.     if ( gHasServerDispatch == true )
  1067.     {
  1068.         gErr = MySCServerVersion(gServerExtensionName, &gServerType, &gServerVersion);
  1069.         gErr = MySCPollServer(&gServerState, &gDisconnectState, &gServerError, &gSecondsLeft);
  1070.         gErr = MySCGetSetupInfo(&gSetupInfoRec, &gMaxVolumes, &gMaxExpFolders, &gCurMaxSessions);
  1071.     }
  1072. }
  1073.